package com.cy.sys.shiro;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;


import com.cy.sys.log.Dao.SysConsumerDao;
import com.cy.sys.log.Dao.SysMenusDao;
import com.cy.sys.log.Dao.SysRoleUserDao;
import com.cy.sys.log.Dao.SysUserDao;
import com.cy.sys.pojo.SysUsersinsert;


//@Service
public class shiroAuthenSerivce extends AuthorizingRealm {
	
	//注入对象
	@Autowired
	private SysConsumerDao sysuserdao;
	//授权注入
	@Autowired
	private SysUserDao sysuserroledao;
	
	@Autowired
	private SysRoleUserDao sysmenroledao;
	
	@Autowired
	private SysMenusDao	sysmenudao;
	
	
	//授权操作
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		
		System.out.println("==doGetAuthorizationInfo===");
		SysUsersinsert user = (SysUsersinsert)principals.getPrimaryPrincipal();
		//基于用户id查询角色id并校验
		List<Integer> roleids =sysuserroledao.findRoleuserById(user.getId());		
		if(roleids==null||roleids.size()<0)
			throw new AuthorizationException();
		//基于角色id查询菜单id并校验
		List<Integer> menuids = sysmenroledao.findRolemensintger(roleids);
		if(menuids==null||menuids.size()<0)
			throw new AuthorizationException();
		//基于菜单id查询授权标识并校验
		List<String> menusSTRING = sysmenudao.findMenusStringprop(menuids);
		if(menusSTRING==null||menusSTRING.size()==0)
			throw new AuthorizationException();
		//5.封装查询结果并返回
		Set<String> stringPermissions=new HashSet<>();
		
		for (String pre : menusSTRING) {
			if(pre!=null&&!"".equals(pre)) {
				stringPermissions.add(pre);
			}
		}
		
		SimpleAuthorizationInfo sim = new SimpleAuthorizationInfo();
		sim.setStringPermissions(stringPermissions);
		return sim;
	}
	
	
	
	//认证信息操作
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//1.需要从token中获得用户名级密码怎么办?
		UsernamePasswordToken Utoken = (UsernamePasswordToken)token;//token强转成子类对象可获得
		String username = Utoken.getUsername();
		//2.从数据库查询
		SysUsersinsert sysusers = sysuserdao.selectById(username);
		//3.对查询结构进行判断
		if(sysusers==null)
			throw new UnknownAccountException();//用户名不知道异常
		//3.1判断是否被锁定
		if(sysusers.getValid()==0)
			throw new LockedAccountException();//用户名被锁定异常
		//由于盐值传递的必须是
		ByteSource credentialsSalt = ByteSource.Util.bytes(sysusers.getSalt());
		//4.封装用户信息并返回.?不知道返回的是什么,看方法的返回值
		SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
				sysusers, // 用户身份
				sysusers.getPassword(), //数据库的密码(已被)
				credentialsSalt, //盐值
				getName());//认证对象返回
		return info;
	}
	
	
	//设置凭证匹配器:还有一种方式为get
	@Override
	public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
		//构建匹配器对象
		HashedCredentialsMatcher credent = new HashedCredentialsMatcher();
		//设置加密算法
		credent.setHashAlgorithmName("MD5");
		//设计几次加密与添加用户时相同次数
		credent.setHashIterations(1);
		super.setCredentialsMatcher(credent);
	}
}
